<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    //2021-06-24-夜-丰台-补充-阅览《你不知道的js书》 

    //立即执行的函数  
    // 声明完函数以后，立即执行该函数
    (function () {
        console.log('watch out!');
    } ());  

    //这种方式声明的函数，也可以立即执行 
    !function () {
        console.log('watch out!');
    } ();

    // 如下方式也都可以哦
    ~function () { /* code */ } (); 
    -function () { /* code */ } (); 
    +function () { /* code */ } (); 



// 我们在下面看这段代码 函数作用域的 使用自执行函数优化一下 
    var a = 2;
    function foo(){   //添加这一行 
        var a = 3;
        console.log(a);
    }                 //以及这一行    
    foo()             //调用这一行  
    console.log(a)    
    // log  3 2 
    /*解析问题 
        必须声明一个具名函数foo(),则意味着foo这个名称本身污染了所在作用域 
        其次,必须显式通过函数名foo()调用这个函数,才会执行函数体中的代码片段,运行代码   
      注意！
         如果函数不要需要函数名(就是说函数名可以不污染所以的作用域)
         并且可以自动去执行,这样会更加的理想 
         也就是自执行函数  优化一下上面的代码 
    */
    var a = 2;
    (function foo(){                    //函数被包含在一对()中 因此成为一个表达式  
        var a = 3;
        console.log(a)
    })()                                //通过末尾加另一个()可立即执行这个函数  即代表立即执行函数表达式
    console.log(a);
    //log  3  2    


                //进阶用法把它们当作函数调用并传递参数进去 
   var b = [1,2,3]             
   var a = 2;
   (function IIFE(global){
    var a = 3;
        console.log(a)
        console.log(global.a)
        console.log(global.b)   //拿到b

   })(window)       //我们将window对象的引用传递进去 但将参数命名为global
                    //因此在代码的风格上对全局对象的引用 变得比引用一个没有全局字样的变量更加清晰 
                    //当然可以从外部作用域传递任何你需要的东西 并将变量命名为任何合适的名字(语义化) 
                    //这对改进代码式非常有帮助的 
   console.log(a)
   // log 3 2 [] 

    
   var a = 1;
    (function a () {
        a = 2;
        console.log(a);   //这里打印出来的时函数体 
    //立即调用的函数表达式（IIFE） 有一个 自己独立的作用域，
    //如果函数名称与内部变量名称冲突，就会永远执行函数本身；所以上面的结果输出是函数本身；
    })();
    // 写出执行结果，并解释原因




</script>